/**
 * Copyright (C), 2016-2019, 赋拓物联网技术有限公司
 * FileName: UserControllerAnd
 * Author:   Administrator
 * Date:     2019/6/12 13:38
 * Description: UserControllerAnd
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 **/
package com.scs.application.modules.upms.controller;

import cn.afterturn.easypoi.csv.CsvExportUtil;
import cn.afterturn.easypoi.csv.entity.CsvExportParams;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.core.excel.handler.ExcelDictHandlerImpl;
import com.scs.application.core.exceptions.BusinessException;
import com.scs.application.core.exceptions.ExportException;
import com.scs.application.core.exceptions.ImportException;
import com.scs.application.core.global.GlobalParamService;
import com.scs.application.core.model.CommonResult;
import com.scs.application.core.model.ImportResult;
import com.scs.application.core.model.PageResult;
import com.scs.application.core.model.RestResult;
import com.scs.application.core.mvc.controller.CrudController;
import com.scs.application.core.mvc.controller.ImAndExAbleController;
import com.scs.application.core.utils.*;
import com.scs.application.modules.design.service.QueryGenerator;
import com.scs.application.modules.upms.dto.UserDTO;
import com.scs.application.modules.upms.entity.Office;
import com.scs.application.modules.upms.entity.Role;
import com.scs.application.modules.upms.entity.User;
import com.scs.application.modules.upms.mapper.OfficeMapper;
import com.scs.application.modules.upms.mapper.UserMapper;
import com.scs.application.modules.upms.request.UserQueryRequest;
import com.scs.application.modules.upms.request.UserResetPasswordRequest;
import com.scs.application.modules.upms.security.UserPrincipal;
import com.scs.application.modules.upms.security.integration.authenticator.WxmpAuthenticator;
import com.scs.application.modules.upms.service.MenuService;
import com.scs.application.modules.upms.service.RoleService;
import com.scs.application.modules.upms.service.UserService;
import com.scs.application.modules.upms.vo.UserVO;
import com.scs.application.modules.upms.wxmp.handler.SubscribeHandler;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpQrcodeService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:UserController
 **/
@AllArgsConstructor
@RestController
@RequestMapping("/upms/users")
public class UserController extends CrudController<User, String, UserService> implements ImAndExAbleController<UserQueryRequest> {
    private OfficeMapper officeMapper;
    private UserMapper userMapper;

    private final RoleService roleService;

    private final MenuService menuService;

    @PutMapping("/assignRole")
    public CommonResult assignRole(@RequestBody User user) {
        boolean bUpdate = service.updateById(user);
        return bUpdate ? CommonResult.ok("保存成功", user) : CommonResult.error("保存失败", user);
    }


    @GetMapping("page")
    public PageResult page(UserQueryRequest request) {

        IPage page = service.page(request);
        return PageResult.ok("查询成功", page.getRecords(), page.getTotal());
    }

    @GetMapping("/list")
    public CommonResult list(UserQueryRequest request) {
        List<User> list = service.list(Wrappers.<User>query().orderByDesc("gmt_modified"));
        return CommonResult.ok("查询成功", list);
    }


    /**
     * 获取当前用户全部信息
     *
     * @return 用户信息
     */
    @GetMapping(value = {"/info"})
    public CommonResult info() {
        UserPrincipal userPrincipal = UserUtils.currentUser();
        if (userPrincipal == null) {
            return CommonResult.error("获取当前用户信息失败");
        }

        if (userPrincipal.getRolesId() == null || userPrincipal.getRolesId().isEmpty()) {
            return CommonResult.ok("获取当前用户信息成功", userPrincipal);
        }

        Collection<Role> roles = roleService.listByIds(userPrincipal.getRolesId().toJavaList(String.class));
        userPrincipal.setRoleCodes(roles.stream().map(o -> o.getCode()).collect(Collectors.toList()));

        // 获取用户权限
        List<String> permissions = menuService.getPermissions(userPrincipal.getId());
        userPrincipal.setPermissions(permissions);
        userPrincipal.setVersionApi(GlobalConsts.VERSION_API);

        return CommonResult.ok("获取当前用户信息成功", userPrincipal);
    }


    @Override
    public void excelExport(UserQueryRequest request) {
        String fileName = "用户信息" + DateUtils.format(DateUtils.now(), DateUtils.YYYYMMDDHHMMSS_PATTER) + ".xlsx";

        List<UserVO> list = service.list(request);
        try {
            setDownloadParam(fileName);
            PoiUtils.exportExcel(response().getOutputStream(), "用户信息", UserVO.class, list);
        } catch (IOException e) {
            throw new ExportException("导出异常", e);
        }
    }

    @Override
    public void excelTemplate(UserQueryRequest request) {
        String fileName = "用户导入模板.xlsx";

        request.setCurrPage(1);
        request.setPageSize(10);
        List<UserVO> list = service.page(request).getRecords();

        try {
            // 转为 DTO 对象
            List<UserDTO> dtos = BeanUtils.copyProperties(list, UserDTO.class);

            setDownloadParam(fileName);

            PoiUtils.exportExcel(response().getOutputStream(), "用户导入模板", UserDTO.class, dtos, true);
        } catch (IOException e) {
            throw new ExportException("导出异常", e);
        }
    }

    @Override
    public CommonResult<ImportResult> excelImport(MultipartFile file) throws ImportException {
        return CommonResult.ok("导入成功", service.excelImport(file));
    }

    @PostMapping("/password")
    public CommonResult resetPassword(@RequestBody @Valid UserResetPasswordRequest request) {
        boolean success = service.modifyPassword(request.getId(), request.getOldPassword(), request.getNewPassword());
        return success ? CommonResult.ok() : CommonResult.error();
    }


    @Override
    public void csvExport(UserQueryRequest request) throws ExportException {
        String fileName = "用户信息" + DateUtils.format(DateUtils.now(), DateUtils.YYYYMMDDHHMMSS_PATTER) + ".csv";

        List<UserVO> list = service.list(request);
        CsvExportParams params = new CsvExportParams();
        params.setDictHandler(ExcelDictHandlerImpl.getInstance());

        try {
            setDownloadParam(fileName);
            CsvExportUtil.exportCsv(params, UserVO.class, list, response().getOutputStream());
        } catch (IOException e) {
            throw new ExportException("导出异常", e);
        }
    }


    @PostMapping("/{id}/active")
    public CommonResult active(@PathVariable("id") String id) {
        User user = new User();
        user.setInactive(User.INACTIVE_ENABLED);
        user.setId(id);
        boolean success = service.updateById(user);
        return success ? CommonResult.ok("启用成功") : CommonResult.error("启用失败");
    }

    @PostMapping("/{id}/disable")
    public CommonResult disable(@PathVariable("id") String id) {
        User user = new User();
        user.setInactive(User.INACTIVE_DISABLED);
        user.setId(id);
        boolean success = service.updateById(user);
        return success ? CommonResult.ok("停用成功") : CommonResult.error("停用失败");
    }

    @PostMapping("/{id}/resetPassword")
    public CommonResult resetPassword(@PathVariable("id") String id) {
        service.resetPassword(id);
        return CommonResult.ok("重置成功，默认密码: "+ GlobalParamService.getInstance().getDefaultPassword());

    }

    private final WxMpService wxMpService;

    /**
     * 获取当前用户微信绑定的二维码
     */
    @GetMapping("/qrcode_bind_url")
    public CommonResult getQrcodeBindUrl(@RequestParam("mpKey") String mpKey) {
        wxMpService.switchoverTo(mpKey);
        WxMpQrcodeService qrcodeService = wxMpService.getQrcodeService();

        String userId = UserUtils.currentUser().getId();

        Map map = Maps.newHashMap();
        map.put("userId", userId);
        map.put("action", SubscribeHandler.ACTION_BIND_USER);

        try {
            String url = CacheUtils.getString(WxmpAuthenticator.OAUTH_TYPE, userId);
            if (StringUtils.isBlank(url)) {
                String sceneStr = JSON.toJSONString(map);
                WxMpQrCodeTicket wxMpQrCodeTicket = qrcodeService.qrCodeCreateTmpTicket(sceneStr, 60 * 60);
                url = qrcodeService.qrCodePictureUrl(wxMpQrCodeTicket.getTicket(), true);
                CacheUtils.put(WxmpAuthenticator.OAUTH_TYPE, userId, url);
            }

            return CommonResult.ok("生成成功", url);
        } catch (WxErrorException e) {
            e.printStackTrace();
            throw new BusinessException("二维码生成失败");
        }
    }

    /***
     * @param request
     * @Description:  通用分页
     */
    @Override
    @GetMapping("/pageCommon")
    public PageResult pageCommon(HttpServletRequest request, User entity) {
        IPage<Office> page = QueryGenerator.parsePage(request);
        QueryWrapper<User> queryWrapper = QueryGenerator.initQueryWrapper(request);
        fillQueryAuth(queryWrapper,entity);
        IPage pageResult = userMapper.pageCommon(page, queryWrapper);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }


    /***
     * @param id
     * @Description:  通用查找，单个
     */
    @Override
    @GetMapping("/findByIdCommon")
    public RestResult findByIdCommon(@RequestParam("id") Serializable id) {
        User entity = service.getById(id);
        if (entity == null) {
            return RestResult.error("数据查询失败<br>可能所操作数据已被删除，请刷新后重新尝试操作");
        }
        fillData(entity);
        return RestResult.ok("获取数据成功", entity);
    }

    private void fillData(User entity) {
        Office parent =  officeMapper.selectById(entity.getOfficeId());
        if (parent == null) {
            return;
        }
        entity.setOfficeName(parent.getName());
    }

    /***
     * @param entity
     * @Description:  通用保存、更新
     */
    @Override
    @PostMapping("/saveOrUpdateCommon")
    public RestResult saveOrUpdateCommon(@Valid @RequestBody User entity) {
        boolean isNew = entity.isNewRecord();
        if (isNew) {
            entity.setPassword(Md5Utils.md5(GlobalParamService.getInstance().getDefaultPassword()));
        }
        int count = service.count(Wrappers.<User>query().eq("login_key", entity.getLoginKey()).ne("id",entity.getId()));
        if (count > 0) {
            throw new BusinessException("登录账号不允许重复");
        }

        boolean isOk = service.saveOrUpdate(entity);
        if (!isOk) {
            return RestResult.error("操作失败");
        }
        fillData(entity);
        if (isNew) {
            return RestResult.ok(StrUtil.format("用户新增成功，默认密码: {}",GlobalParamService.getInstance().getDefaultPassword()), entity);
        }
        return RestResult.ok("用户修改成功", entity);
    }

    /**
     * 判断当前登录用户是否是默认密码
     *
     * @return 用户信息
     */
    @GetMapping(value = {"/isDefaultPwd"})
    public CommonResult isDefaultPwd() {
        UserPrincipal userPrincipal = UserUtils.currentUser();
        // 默认密码
        String defaultPassword = GlobalParamService.getInstance().getDefaultPassword();
        if (Md5Utils.md5(defaultPassword).equals(userPrincipal.getPassword())) {
            return CommonResult.ok("操作成功",true);
        }

        return CommonResult.ok("操作成功",false);
    }

}

